/******************** (C) COPYRIGHT 2018 merafour ********************
* Author             : 冷月追风@merafour.blog.163.com
* Version            : V1.0.0
* Date               : 8/1/2019
* Description        : 设备同步与基本通讯指令.
********************************************************************************
* merafour.blog.163.com
* merafour@163.com
* github.com/Merafour
*******************************************************************************/
#include "qiserialsync.h"

QiSerialSync::QiSerialSync(QObject *parent) : QiSerialPort(parent)
{
    ;
}

int QiSerialSync::__scan()
{
    uint8_t buf[2];
    buf[0] = Code::GET_SYNC;
    buf[1] = Code::EOC;
    this->clear();
    QThread::msleep(1);
    __send(buf, 2);
    watting_data(10);
    uint8_t insync = __recv();
    uint8_t ok = __recv();
    //return __getSync();
    if((static_cast<uint8_t>(Code::INSYNC) == insync) && (static_cast<uint8_t>(Code::OK) == ok)) return 0;
    return -1;
}

void QiSerialSync::__send(const uint8_t buf[], const uint32_t len)
{
    //write((const char *)buf, len);
    write(reinterpret_cast<const char *>(buf), len);
}

int QiSerialSync::__sync()
{
    uint8_t buf[2];
    buf[0] = Code::GET_SYNC;
    //buf[0] = Code::GET_CRC;
    buf[1] = Code::EOC;
    //my_port->clear();
//    buffer.clear();
    this->clear();
    QThread::msleep(1);
    __send(buf, 2);
    //QThread::msleep(1);
    watting_data(100);
    //have_data(1);
    return __getSync();
}

int QiSerialSync::__getSync()
{
    //qDebug("Sync[%3d]: %02X %02X %02X %02X %02X %02X", recv_len, recv_data[0], recv_data[1], recv_data[2], recv_data[3], recv_data[4], recv_data[5]);
    uint8_t c = __recv();
    if(static_cast<uint8_t>(Code::INSYNC) != c)
    //if (c != (uint8_t)Code::INSYNC)
    {
        qDebug("unexpected {%0X} instead of INSYNC", c);
        return -1;
    }
    c = __recv();
    //if (c == (uint8_t)Code::INVALID)
    if(static_cast<uint8_t>(Code::INVALID) == c)
    {
        qDebug("bootloader reports INVALID OPERATION:%0X", c);
        return -1;
    }
    //if (c == (uint8_t)Code::FAILED)
    if(static_cast<uint8_t>(Code::FAILED) == c)
    {
        qDebug("bootloader reports OPERATION FAILED:%0X", c);
        return -1;
    }
    //if (c != (uint8_t)Code::OK)
    if(static_cast<uint8_t>(Code::OK) != c)
    {
        qDebug("unexpected {%0X} instead of OK", c);
        return -1;
    }
    return 0;
}

int QiSerialSync::__recv_int()
{
#if 0
    uint8_t raw[4];
    memset(raw, 0, sizeof(raw));
    __recv(raw, 4);
    int val = (raw[0]&0xFF) | (raw[1]&0xFF<<8) | (raw[2]&0xFF<<16) | (raw[3]&0xFF<<24);
    return val;
#else
    uint8_t raw[4];
    memset(raw, 0, sizeof(raw));
    __recv(raw, 4);
    //int val = (raw[0]&0xFF) | (raw[1]&0xFF<<8) | (raw[2]&0xFF<<16) | (raw[3]&0xFF<<24);
    uint32_t val=0;
    val = raw[3]&0xFF;
    val <<= 8; val |= raw[2]&0xFF;
    val <<= 8; val |= raw[1]&0xFF;
    val <<= 8; val |= raw[0]&0xFF;
    //val = (val<<8) | raw[2]&0xFF;
//    val = (val<<8) | raw[1]&0xFF;
//    val = (val<<8) | raw[0]&0xFF;
    //return (int)val;
    return  static_cast<int>(val);
#endif
}

int QiSerialSync::__getInfo(QiSerialSync::Info param)
{
    uint8_t buf[3];
    buf[0] = Code::GET_DEVICE;
    buf[1] = param;
    buf[2] = Code::EOC;
    this->clear();
    QThread::msleep(1);
    __send(buf, 3);
    //QThread::msleep(1500);
    int info = __recv_int();
    __getSync();
    qDebug("info:%0X %d", info, info);
    return info;
}

int QiSerialSync::identify()
{
    if(0!=__sync())
    {
        return -1;
    }
    bl_rev=__getInfo(Info::BL_REV);
//     if ((bl_rev < (int)BL_REV_MIN) || (bl_rev > (int)BL_REV_MAX))
//     {
//         throw new Exception("Bootloader protocol mismatch");
//     }

     board_type = __getInfo(Info::BOARD_ID);
     board_rev = __getInfo(Info::BOARD_REV);
     fw_maxsize = __getInfo(Info::FLASH_SIZE);
    return 0;
}
